<template>
  <div class="banner">
    <div
      ref="banner"
      :style="bannerStyle"
      @touchstart="touchstart($event)"
      @touchmove="touchmove($event)"
      @touchend="touchend($event)"
      class="list"
    >
      <div class="item" v-for="(item,index) in list" :key="index" :style="{width:`${itemWidth}px`}">
        <slot :item="item"></slot>
      </div>
    </div>
    <div class="progress">
      <div
        class="progress_item"
        v-for="(item,index) in list.length"
        :key="index"
        :class="{'select':index==displayIndex}"
        @click="displayIndex=index"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Slider",
  props: {
    initPage: {
      type: Boolean,
      default: false,
    },
    list: {
      type: Array,
      default: () => {
        return [];
      },
    },
    changeWidth: {
      type: Number,
      default: 0,
    },
  },
  computed: {
    optionsStyle() {
      return {
        width: "0px",
        height: "0px",
        transitionDuration: "0",
        transform: "translate(0,0)",
        ...this.bannerStyle,
      };
    },
  },
  data() {
    return {
      bannerStyle: {},
      itemWidth: 0,
      itemHeight: 0,
      displayIndex: 0,
      slidePosition: "left",
    };
  },
  watch: {
    initPage(val) {
      if (val) {
        this.bannerStyle = {
          width: this.itemWidth * (this.list.length + 1) + "px",
          height: this.itemHeight + "px",
          transitionDuration: "0",
          transform: "translate3d(0,0,0)",
        };
        this.displayIndex = 0;
      }
    },
    displayIndex(value) {
      setTimeout(() => {
        if (value >= 0) {
          this.bannerStyle = {
            width: this.itemWidth * (this.list.length + 1) + "px",
            height: this.itemHeight + "px",
            transitionDuration: "500ms",
            transform: `translate3d(${-value * this.itemWidth}px,0,0)`,
          };
          this.transitionendCallback(() => {
            if (value >= this.list.length) {
              this.bannerStyle.transform = "translate3d(0,0,0)";
              value = 0;
            }
          });
          this.changeSlider();
        } else {
          this.displayIndex = 0;
        }
      }, 0);
    },
  },
  created() {
    this.$nextTick(() => {
      this.itemWidth = window.innerWidth - this.changeWidth;
      this.itemHeight = window.innerHeight;
      this.bannerStyle = {
        width: this.itemWidth * (this.list.length + 1) + "px",
        height: this.itemHeight + "px",
        transform: `translate3d(${-this.displayIndex * this.itemWidth}px,0,0)`,
      };
      this.$refs.banner.addEventListener(
        "transitionend",
        this.transitionendCallback(),
        false
      );
    });
  },
  methods: {
    touchstart(e) {
      this.startX = e.touches.length === 1 ? e.touches[0].clientX : 0;
    },
    touchmove(e) {
      this.isSlider = true;
      if (e.touches.length === 1) {
        // 滑动时距离浏览器左侧的距离
        this.moveX = e.touches[0].clientX;
        if (this.startX - this.moveX < 0) {
          // 右滑
          this.slidePosition = "right";
          if (this.displayIndex > 0) {
            this.bannerStyle = {
              width: this.itemWidth * (this.list.length + 1) + "px",
              height: this.itemHeight + "px",
              transform: `translate3d(${
                -this.displayIndex * this.itemWidth - this.startX + this.moveX
              }px,0,0)`,
            };
          }
        } else if (this.startX - this.moveX > 0) {
          // 左滑
          if (this.displayIndex + 1 < this.list.length) {
            this.slidePosition = "left";
            this.bannerStyle = {
              width: this.itemWidth * (this.list.length + 1) + "px",
              height: this.itemHeight + "px",
              transform: `translate3d(${
                -this.displayIndex * this.itemWidth - this.startX + this.moveX
              }px,0,0)`,
            };
          }
        }
      }
    },
    touchend() {
      if (!this.isSlider) return;
      if (Math.abs(this.moveX - this.startX) > 50) {
        //滑动距离大于50就移动
        if (this.slidePosition === "left") {
          if (this.displayIndex + 1 < this.list.length) this.displayIndex++;
        } else {
          this.displayIndex--;
        }
      } else {
        // 不移动
        this.bannerStyle = {
          width: this.itemWidth * (this.list.length + 1) + "px",
          height: this.itemHeight + "px",
          transitionDuration: "0ms",
          transform: `translate3d(${
            -this.displayIndex * this.itemWidth
          }px,0,0)`,
        };
      }
      this.isSlider = false;
    },
    transitionendCallback(fn) {
      if (fn && typeof fn == "function") fn();
    },
    changeSlider() {
      this.$emit("change", this.displayIndex);
    },
  },
};
</script>

<style scoped lang="scss">
@import "../style/index.scss";
.banner {
  position: relative;
  overflow: hidden;
  @include wh(100%, 100%);
  .list {
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    .item {
      float: left;
      @include wh(auto, 100%);
    }
  }
  .progress {
    position: absolute;
    bottom: 50px;
    left: 50%;
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    -o-transform: translate3d(0, 0, 0);
    transform: translate3d(-50%, 0, 0);
    .progress_item {
      @include wh(12px, 12px);
      display: inline-block;
      margin-right: 10px;
      border-radius: 50%;
      background: $btnLightColor;
      &.select {
        background: $btnColor;
      }
    }
  }
}
</style>